// +----------------------------------------------------------------------
// | Manong.Cloud [ 领酷码农云 ]
// +----------------------------------------------------------------------
// | Copyright (c) 2020 http://www.manong.cloud All rights reserved.
// +----------------------------------------------------------------------
// | Author: 稻草人 <qinuoyun@qq.com>
// +----------------------------------------------------------------------
// | Member: 围棋 飘逸者 Loumt Silence24
// +----------------------------------------------------------------------

//初始化常量
import "./system/initialize.js";
import "./system/functions.js";
import "./system/config/common.js";

//加载系统公共类文件
import "./system/common/BasicController.js";
import "./system/common/CommonModels.js";
import "./system/common/ContentContext.js";

//加载系统插件类
import _database from "./system/plugin/database";
import _request from "./system/plugin/request/index.js";
import _cache from "./system/plugin/cache/index.js";
import _wechat from "./system/plugin/wechat/index.js";
import _lightcode from "./system/plugin/lightcode/index.js";
import _api from "./system/plugin/api";
import _vhost from "./system/plugin/vhost";

import websocket from "./system/plugin/websocket";
import error from "./system/plugin/error";

//加载公共系统插件
import koa from "koa";
import path from "path";
import koaLogger from "koa-logger";
import koaJson from "koa-json";
import koaStatic from "koa-static";
import koaViews from "koa-views";
import koaJwt from "koa-jwt";
import koaBody from "koa-body";
import cors from "koa2-cors";
import mount from "koa-mount";


process.env.PORT = C("port");

//初始化数据库插件
let _db_config = C("database");
if (_db_config.dialect) {
  global.db = _database.connect(C("database"));
}

//初始化缓存

global.cache = _cache;

//初始化HTTP请求工具
global.request = new _request();

//初始化HTTP请求工具
global.wechat = _wechat;

//轻代码核心处理器
global.lightcode = _lightcode;


//初始化secret用于JWT鉴权使用保证加密和解析的用的是相同的
global.__SECRET__ = C("components.jwt.key");

const app = new koa();


//处理跨域容器
app.use(
  cors({
    origin: function (ctx) { //设置允许来自指定域名请求
      let origin = "*";
      if (ctx.headers.origin) {
        origin = rtrim(ctx.headers.origin, "/");
      }
      return origin;
    },
    maxAge: 5, //指定本次预检请求的有效期，单位为秒。
    credentials: true, //是否允许发送Cookie
    allowMethods: ["GET", "POST", "PUT", "DELETE", "OPTIONS"], //设置所允许的HTTP请求方法'
    allowHeaders: ["Content-Type", "Authorization", "Accept"], //设置服务器支持的所有头信息字段
    exposeHeaders: ["WWW-Authenticate", "Server-Authorization", "APPID", "mn-cloud-appid", "mn-cloud-env", "mn-cloud-file"] //设置获取其他自定义字段
  })
);

//设置KOA视图加载目录
app.use(koaViews(ROOT_DIR + "/views", {
  extension: "html"
}));

//加载JSON中间件
app.use(koaJson());
//获取数据内容
app.use(koaBody({
  multipart: true,
  formidable: {
    maxFileSize: 1000 * 1024 * 1024 // 设置上传文件大小最大限制，默认2M
  }
}));


app.use(_vhost({
  "a101.manong.cloud": "/admin"
}));


//错误信息收纳器
app.use(error());
//加载日志中间件
app.use(koaLogger());

//处理运行时间
app.use(async (ctx, next) => {
  const start = new Date();
  await next();
  const ms = new Date() - start;
  console.log(`${ctx.method} ${ctx.url} - ${ms}ms`);
});


// 设置静态目录-用于上传文件视频等
app.use(koaStatic(ROOT_DIR + "/public"));

// 设置虚拟目录结构
app.use(mount("/css", koaStatic(ROOT_DIR + "/views/css")));
app.use(mount("/fonts", koaStatic(ROOT_DIR + "/views/fonts")));
app.use(mount("/img", koaStatic(ROOT_DIR + "/views/img")));
app.use(mount("/js", koaStatic(ROOT_DIR + "/views/js")));
app.use(mount("/smart_building", koaStatic(ROOT_DIR + "/views/smart_building")));
app.use(mount("/favicon.ico", koaStatic(ROOT_DIR + "/views/favicon.ico")));

// 加载路由信息
let index = require("./system/views");
app.use(index.routes(), index.allowedMethods());

// 处理预请求问题
app.use(async (ctx, next) => {
  if (ctx.method == "OPTIONS") {
    ctx.body = 204;
    return;
  } else {
    await next();
  }
});
//JWT中间件
app.use(koaJwt({
  secret: __SECRET__
}).unless({
  //设置白名单信息
  path: ["/favicon.ico"].concat(C("whitelist"))
}));

//鉴权通过后执行的数据用户数据交换
app.use(async (ctx, next) => {
  try {
    global.originUrl = ctx.request.header.origin;
    //读取用户信息类
    let identityClass = getComponent(C("components.user.identityClass"));
    //过滤白名单信息
    let is_white = matchesPath(ctx.request.url, C("whitelist"));
    // ctx.set('aaa', '222')

    //判断是否是函数
    if (Object.prototype.toString.call(identityClass) == "[object Function]" && ctx.request.header.authorization && !is_white) {
      if (identityClass.findIdentityByAccessToken && Object.prototype.toString.call(identityClass.findIdentityByAccessToken) == "[object Function]") {
        let userinfo = await identityClass.findIdentityByAccessToken(ctx.request.header.authorization);
        ctx.state = {
          user: userinfo,
          APPID: ctx.headers["mn-cloud-appid"] || ctx.headers["appid"] || ctx.headers["APPID"] || 0
        };
        await next();
      }
    } else {
      await next();
    }
  } catch (error) {
    throw error;
  }
});


// 加载API路由
app.use(_api.routes(), _api.allowedMethods());


// 创建一个链接库，需要在WWW中后置运行
app.__socket = function (app, server) {
  //判断是否需要开启IO链接
  if (C("components.socket.enableConnection")) {
    try {
      let component = getComponent(C("components.socket.class"));
      //获取所有链接的方法名
      let connections = Object.getOwnPropertyNames(component.prototype);
      websocket.init(server, component)
    } catch (error) {
      throw error;
    }
  }
};

export default app;
